﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DevComponents.DotNetBar;
using PlanningGIS.Framework;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataManagementTools;
using ESRI.ArcGIS.Geoprocessor;
using ESRI.ArcGIS.Geometry;
using System.Runtime.InteropServices;
using PlanningGIS.Win.Controls;
using PlanningGIS.Engine.Controls;
using PlanningGIS.ArcGIS;
using ESRI.ArcGIS.DataSourcesGDB;

namespace PlanningGIS.Product
{
    public partial class FrmMdImportLocal : Office2007Form
    {
        private LogPanel logPanel;
        private IApplication m_Application;

        public FrmMdImportLocal(IApplication value)
        {
            InitializeComponent();
            ctlSelectData1.CanSelectMultiple = true;
            ctlSelectData1.SelectDataStructureType = PlanningGISDataStructureType.FEATURECLASS;
            m_Application = value;
        }

        private void btnOpenLoaclDb_Click(object sender, EventArgs e)
        {
            try
            {
                OpenDataDialog selectData = new OpenDataDialog();
                selectData.OnOkClick = delegate
                {
                    string strPath = selectData.FullName.TrimEnd('\\');

                    if (strPath.ToLower().EndsWith(".gdb") || strPath.ToLower().EndsWith(".mdb"))
                    {
                        txtLoaclDbPath.Text = selectData.FullName;
                        selectData.Close();
                    }
                    else
                    {
                        MsgHelper.ShowWarningMsgbox("请选择空间数据库（GDB、MDB）数据！");
                        return;
                    }

                };

                selectData.MultiSelect = false;
                selectData.ShowDialog(this);
            }
            catch (Exception ex)
            {
                MsgHelper.ShowErrorMsgbox(ex.Message);
            }
        }

        private void FrmMdImportLocal_Load(object sender, EventArgs e)
        {
            cbo_metadataType.SelectedIndex = 0;
            cbo_databaseType.SelectedIndex = 0;

            #region 弹出日志
            IDockManager frameController = (m_Application as IFramework).DockManager;
            logPanel = (m_Application as IFramework).GetControlUserData("日志") as LogPanel;
            if (logPanel == null)
            {
                logPanel = new LogPanel();
                frameController.AddDockPanel("日志", logPanel, false, esriDockFlags.esriDockBottom);
            }
            frameController.ActivateDockPanel("日志");
            #endregion
        }

        private void btnImport_Click(object sender, EventArgs e)
        {
            #region 1条件判断
            List<FeatureClassNode> fcList = ctlSelectData1.SelectFeatureClasses;
            if (fcList.Count==0)
            {
                MsgHelper.ShowErrorMsgbox("请选择待导入的元数据图层！");
                return;
            }

            PlanningGISMetadataType metadataType;
            string metadataFCName = "";

            switch (cbo_metadataType.SelectedItem.ToString())
            {
                case "数据库级元数据": 
                    metadataType = PlanningGISMetadataType.DATABASE_LEVEL;
                    //metadataFCName = metadataFCName+"_DB";
                    break;
                case "DLG测区级元数据": 
                    metadataType = PlanningGISMetadataType.REGION_LEVEL_DLG;
                    //metadataFCName = metadataFCName + "_RG";
                    break;
                case "DEM测区级元数据":
                    metadataType = PlanningGISMetadataType.REGION_LEVEL_DEM;
                    //metadataFCName = metadataFCName + "_RG";
                    break;
                case "DOM测区级元数据":
                    metadataType = PlanningGISMetadataType.REGION_LEVEL_DOM;
                    //metadataFCName = metadataFCName + "_RG";
                    break;
                case "图幅级元数据": 
                    metadataType = PlanningGISMetadataType.MAPSHEET_LEVEL;
                    //metadataFCName = metadataFCName+"_MS";
                    break;
                case "要素级元数据": 
                    metadataType = PlanningGISMetadataType.FEATURE_LEVEL;
                    //metadataFCName = metadataFCName+"_FT";
                    break;
                default: MsgHelper.ShowErrorMsgbox("请选择元数据类型！"); return;
            }

            PlanningGISDatabaseType databaseType;

            //switch(comboBoxEx_scale.SelectedItem.ToString())
            //{
            //    case "1:10000": 
            //        dataScale= PlanningGISDataScale.G;
            //        //metadataFCName = metadataFCName+"_G";
            //        break;
            //    case "1:5000":
            //        dataScale = PlanningGISDataScale.H; 
            //        //metadataFCName = metadataFCName+"_H";
            //        break;
            //    default: MsgHelper.ShowErrorMsgbox("请选择数据比例尺！"); return;
            //}

            switch (cbo_databaseType.SelectedItem.ToString())
            {
                case "基础空间要素数据库(DLG库)":
                    databaseType = PlanningGISDatabaseType.DLG;
                    break;
                case "数字高程模型数据库(DEM库)":
                    databaseType = PlanningGISDatabaseType.DEM;
                    break;
                case "数字正射影像数据库(DOM库)":
                    databaseType = PlanningGISDatabaseType.DOM;
                    break;
                case "元数据数据库(MD库)":
                    databaseType = PlanningGISDatabaseType.MD;
                    break;
                case "地名数据库(PN库)":
                    databaseType = PlanningGISDatabaseType.PN;
                    break;
                case "大地成果数据库DDK库)":
                    databaseType = PlanningGISDatabaseType.DDK;
                    break;
                case "系统维护数据库(MT库)":
                    databaseType = PlanningGISDatabaseType.MT;
                    break;
                case "三维景观数据库(D3库)":
                    databaseType = PlanningGISDatabaseType.D3;
                    break;
                default: MsgHelper.ShowErrorMsgbox("请选择数据库类型！"); return;
            }

            metadataFCName = MetadataHelper.getMetadataFeatureclassDefaultName(metadataType, databaseType);
            FeatureClassNode FCNode = new FeatureClassNode();

            if (txtLoaclDbPath.Text.Trim() == "")
            {
                MsgHelper.ShowErrorMsgbox("请设置本地DLG数据库！");
                return;
            }
            FCNode.Name = metadataFCName;
            FCNode.Path = txtLoaclDbPath.Text;
            IWorkspaceFactory2 wsf = new FileGDBWorkspaceFactoryClass();
            FCNode.WorkspaceType = zjgisWorkspaceType.gdb;
            if (System.IO.Path.GetExtension(txtLoaclDbPath.Text).Equals(".MDB", StringComparison.CurrentCultureIgnoreCase))
            {
                FCNode.WorkspaceType = zjgisWorkspaceType.mdb;
                wsf = new ESRI.ArcGIS.DataSourcesGDB.AccessWorkspaceFactoryClass();
            }

            FCNode.PropertySet = wsf.ReadConnectionPropertiesFromFile(FCNode.Path);
            DataBaseNode DBNode = new DataBaseNode();
            DBNode.Path = FCNode.Path;
            DBNode.WorkspaceType = FCNode.WorkspaceType;
            DBNode.PropertySet = FCNode.PropertySet;

            IDataset targetDS = DBNode.Open();
            IFeatureWorkspace fws = targetDS as IFeatureWorkspace;
            
            
            if (fws != null)
            {
                if (!GeodatabaseHelper.ExistsFeatureClass(DBNode.Workspace, FCNode.Name))
                {
                    MsgHelper.ShowErrorMsgbox("空间数据库中不存在元数据要素类：" + FCNode.Name + "！");
                    return;
                }
            }

            #endregion 1条件判断

            #region 2入库确认
            if (MsgHelper.ShowYesOrNoQueryMsgBox("您确定要进行元数据入库操作吗？") == DialogResult.No) { return; }
            #endregion 2入库确认

            #region 3元数据入库
            try
            {
                this.Height = 506;
                logPanel.Log("开始元数据入本地库...");
                IFeatureClass targetFeatureClass = FCNode.Open() as IFeatureClass;
                bool allError=false;
                bool hasError=false;

                if (ImportMetaData(targetFeatureClass, FCNode.Path, ref allError, ref hasError, ref fcList) == false)
                {
                    logPanel.ErrLog("元数据入本地库出错！\n");
                    MsgHelper.ShowErrorMsgbox("元数据入本地库出错！");
                }
                else
                {
                    logPanel.DoneLog("元数据入本地库完毕。\n");
                    MsgHelper.ShowInfomationMsgbox("元数据入本地库完毕。");
                }

                Cursor = Cursors.WaitCursor;
                Application.DoEvents();
            }
            catch (Exception ex)
            {
                MsgHelper.ShowWarningMsgbox("元数据入本地库失败：" + ex.Message);
            }
            finally
            {
                this.Cursor = Cursors.Default;
                this.Height = 460;
            }
            #endregion 3元数据入库
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 更新数据入库
        /// </summary>
        /// <param name="gdbPath"></param>
        /// <param name="targetPath"></param>
        /// <param name="allError"></param>
        /// <param name="hasError"></param>
        /// <param name="pFeatClses"></param>
        /// <returns></returns>
        private bool ImportMetaData(IFeatureClass pTargetFeatureClass, string targetPath, ref bool allError, ref bool hasError, ref List<FeatureClassNode> pSourceFeatClses)
        {
            string featClsName = "";

            try
            {
                setAllPgbMax(pSourceFeatClses.Count);
                //setSubPgbMax(pSourceFeatClses.Count);
                IDataset datasetTemp = null;
                //IFeatureClass featureClassTemp = null;
                #region 字段一致
                if (rdoFieldSame.Checked==true )
                {
                    //logPanel.Log("开始对[" +  + "]中的数据进行入库。。。");
                    for (int i = 0; i < pSourceFeatClses.Count; i++)
                    {
                        //setSubPgbCurrent(i + 1);
                        setAllPgbCurrent(i + 1);

                        featClsName = pSourceFeatClses[i].Name;

                        logPanel.Log(" 正在对[" + featClsName + "]数据进行入库...");

                        datasetTemp = pSourceFeatClses[i].Open();

                        if (datasetTemp == null)
                        {
                            logPanel.ErrLog("该GDB中未找到[" + featClsName + "]数据，无法进行元数据入库！\n");
                            hasError = true;
                            continue;
                        }

                        string inputs = pSourceFeatClses[i].Path;
                        string target = targetPath + "\\" + (pTargetFeatureClass as IDataset).Name;

                        ESRI.ArcGIS.DataManagementTools.Append append = new ESRI.ArcGIS.DataManagementTools.Append();
                        append.inputs = inputs;
                        append.target = target;
                        append.schema_type = "NO_TEST";

                        string strMsg;
                        bool success = GeoprocessorHelper.Execute(append, out strMsg);

                        if (success)
                        {
                            allError = false;
                            logPanel.DoneLog(strMsg);
                            logPanel.Log(" [" + featClsName + "]元数据入库完毕。\n");
                        }
                        else
                        {
                            hasError = true;
                            logPanel.ErrLog(strMsg);
                        }                        
                    }
                }
                #endregion

                #region 字段不一致(根据字段中文别名)
                if (rdoFieldDiff .Checked  == true)
                {
                    for (int i = 0; i < pSourceFeatClses.Count; i++)
                    {
                        //setSubPgbCurrent(i + 1);
                        setAllPgbCurrent(i + 1);
                        featClsName = pSourceFeatClses[i].Name;
                        logPanel.Log(" 正在对[" + featClsName + "]数据进行入库...");
                        datasetTemp = pSourceFeatClses[i].Open();

                        if (datasetTemp == null)
                        {
                            logPanel.ErrLog("该GDB中未找到[" + featClsName + "]数据，无法进行元数据入库！\n");
                            hasError = true;
                            continue;
                        }

                        IQueryFilter pQueryFilter = null;
                        IFeatureCursor pFeatCur = ((IFeatureClass)datasetTemp).Search(pQueryFilter, false);
                        if (pQueryFilter != null) Marshal.ReleaseComObject(pQueryFilter);
                        IFeature pFeature = null;
                        IFeature pTargetFeature = null;
                        IGeometry geometryTemp = null;
                        int succeed = 0;
                        IGeometryDef geometryDef = pTargetFeatureClass.Fields.get_Field(
                            pTargetFeatureClass.FindField(
                            pTargetFeatureClass.ShapeFieldName)).GeometryDef ;
                        IGeometryDef geometryDef2 = ((IFeatureClass)datasetTemp).Fields.get_Field(
                            ((IFeatureClass)datasetTemp).FindField(
                            ((IFeatureClass)datasetTemp).ShapeFieldName)).GeometryDef;

                        while ((pFeature = pFeatCur.NextFeature()) != null)
                        {
                            pTargetFeature=pTargetFeatureClass.CreateFeature();

                            if (geometryDef.HasZ != geometryDef2.HasZ || geometryDef.HasM != geometryDef2.HasM)
                            {
                                geometryTemp = pFeature.Shape;
                                ((IZAware)geometryTemp).ZAware = geometryDef.HasZ;
                                ((IMAware)geometryTemp).MAware = geometryDef.HasM;
                                pTargetFeature.Shape = geometryTemp;
                            }
                            else
                            {
                                pTargetFeature.Shape = pFeature.Shape;
                            }

                            #region 匹配字段
                            for (int j = 0; j <pTargetFeatureClass.Fields.FieldCount; j++)
                            {
                                string fldName = pTargetFeatureClass.Fields.Field[j].AliasName;

                                if (pTargetFeatureClass.Fields.Field[j].Editable==true)
                                {
                                    //只为可编辑字段赋值，避免处理id、周长、面积等系统字段，xhb20130311
                                    if (fldName == "元数据类型")//元数据类型字段
                                    {
                                        pTargetFeature.set_Value(j, cbo_metadataType.SelectedItem.ToString());                                    
                                    }
                                    else if (fldName == "唯一编码")
                                    {
                                        pTargetFeature.set_Value(j, CommonClass.GetGUID());
                                    
                                    }
                                    else
                                    {
                                        object fldValue = GetCompareField(fldName, pFeature);

                                        if (fldValue != null)
                                        {
                                            pTargetFeature.set_Value(j, fldValue);
                                        }
                                    }
                                }
                            }
                            #endregion

                            pTargetFeature.Store();
                            succeed++;                            
                        }
                        logPanel.Log(" [" + featClsName + "]元数据入库完毕。共成功入库了" + succeed + "个。\n");
                    }
                
                }

                //setSubPgbCurrent(pSourceFeatClses.Count);
                setAllPgbCurrent(pSourceFeatClses.Count);
                #endregion
                return true;
            }
            catch (Exception ex)
            {
                logPanel.ErrLog(" [" + featClsName + "]元数据入库失败：" + ex.Message);

                hasError = true;
                return false;
            }
        }



        #region 进度条
        private void setSubPgbMax(int max)
        {
            progressBarSub.Maximum = max;
            progressBarSub.Minimum = 0;
            progressBarSub.Value = 0;
            Application.DoEvents();
        }

        private void setSubPgbCurrent(int current)
        {
            if (current <= progressBarSub.Maximum)
            {
                progressBarSub.Value = (int)current;

                double dRate = current * 100.0 / progressBarSub.Maximum;
                int iRate = (int)Math.Floor(dRate);
                progressBarSub.TextVisible = true;
                progressBarSub.Text = "分进度：" + current.ToString() + "/" + progressBarSub.Maximum.ToString() + "(" + iRate.ToString() + "%)";

                //dataGridViewX1.UseWaitCursor = true;
            }
            else
            {
                progressBarSub.Value = (int)progressBarSub.Maximum;
                progressBarSub.TextVisible = false;
                //dataGridViewX1.UseWaitCursor = false;
            }
            progressBarSub.Update();
            if (progressBarSub.Maximum < 200)
                Application.DoEvents();
            else
                if (current % (progressBarSub.Maximum / 100) == 0) Application.DoEvents();
        }

        private void setAllPgbMax(int max)
        {
            progressBarAll.Maximum = max;
            progressBarAll.Minimum = 0;
            progressBarAll.Value = 0;
            Application.DoEvents();
        }

        private void setAllPgbCurrent(int current)
        {
            if (current <= progressBarAll.Maximum)
            {
                progressBarAll.Value = (int)current;

                double dRate = current * 100.0 / progressBarAll.Maximum;
                int iRate = (int)Math.Floor(dRate);
                progressBarAll.TextVisible = true;
                progressBarAll.Text = "总进度：" + current.ToString() + "/" + progressBarAll.Maximum.ToString() + "(" + iRate.ToString() + "%)";

                //dataGridViewX1.UseWaitCursor = true;
            }
            else
            {
                progressBarAll.Value = (int)progressBarAll.Maximum;
                progressBarAll.TextVisible = false;
                //dataGridViewX1.UseWaitCursor = false;
            }
            progressBarAll.Update();
            if (progressBarAll.Maximum < 200)
                Application.DoEvents();
            else
                if (current % (progressBarAll.Maximum / 100) == 0) Application.DoEvents();
        }
        #endregion

        /// <summary>
        /// 获取要素中指定别名字段值
        /// </summary>
        /// <param name="pTargetFldAliasName">目标要素类字段别名</param>
        /// <param name="pSourceFeature">源要素</param>
        private object GetCompareField(string pTargetFldAliasName, IFeature pSourceFeature)
        {
            object fldValue = null;

            for (int i = 0; i < pSourceFeature.Fields.FieldCount; i++)
            {
                string fldName = pSourceFeature.Fields.Field[i].Name;   //

                if (pTargetFldAliasName == fldName)
                {
                    fldValue = pSourceFeature.get_Value(i);
                    break;
                }
            }

            return fldValue;
        }

        private void cbo_metadataType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbo_metadataType.SelectedItem.ToString() == "DLG测区级元数据")
            {
                cbo_databaseType.SelectedIndex = getObjCollectionIndex(cbo_databaseType.Items, "基础空间要素数据库(DLG库)");
            }
            else if (cbo_metadataType.SelectedItem.ToString() == "DEM测区级元数据")
            {
                cbo_databaseType.SelectedIndex = getObjCollectionIndex(cbo_databaseType.Items, "数字高程模型数据库(DEM库)");
            }
            else if (cbo_metadataType.SelectedItem.ToString() == "DOM测区级元数据")
            {
                cbo_databaseType.SelectedIndex = getObjCollectionIndex(cbo_databaseType.Items, "数字正射影像数据库(DOM库)");
            }
        }

        private int getObjCollectionIndex(ComboBox.ObjectCollection pItems, string pString)
        {
            for (int i = 0; i < pItems.Count; i++)
            {
                if (pItems[i].ToString() == pString)
                {
                    return i;
                }
            }

            return -1;
        }
    }
}
